#!/usr/bin/python
#-*- coding=utf-8 -*-

import zmq
import time
import ConfigParser
import json
import string
import smtplib
import threading
from email.mime.text import MIMEText
from email.header	 import Header
from SqlManager import SqlManager

import sys 
reload(sys) 
sys.setdefaultencoding('utf8')

DATABASE_NAME = "DB_UPLOAD"
#HOST = "localhost"
HOST = "101.37.30.106"
USER_NAME = 'query_upload'
PASSWORD = "XHFNuyKzQ2A4ZitG"
TB = "TB_MONITOR_DATA"
CHAR_SET = 'utf8'
CONFIG_PATH = '/minik_server_file/monitor.ini'

SENDER = 'david_xcy@163.com'
RECEIVER = ['xcy@ep-audio.com', 'zj@ep-audio.com']
SUBJECT_WARNING = '有监控报警邮件，请注意查收!'
SUBJECT_DAILY = '日常监控邮件，请注意查收'
SMTPSERVER = 'smtp.163.com'
MAIL_PASSWORD = 'flzx3qc'

DAILY_TIME = time.time() + 86400
DISCONN_TIME = 600
MONITOR_DICT = dict()

SQL_CREATE_TB = '''
create table if not exists %s(
TIME_TOKEN varchar(16) not null primary key,
IP		   varchar(16) not null,
band_send  varchar(10),
band_receive varchar(10),
disk	   varchar(2000),
mem_used   varchar(8),
mem_total  varchar(10),
cpu		   varchar(8),
conn_num   bigint	default 0
) ENGINE=InnoDB DEFAULT CHARSET=utf8
''' %TB

def init():
	sqlManager = SqlManager()
	sqlManager.setConnect(DATABASE_NAME, HOST, USER_NAME, PASSWORD, CHAR_SET)
	result = sqlManager.showTables()
	print result
	if result.count((TB,)) == 0:
		sqlManager.createTable(SQL_CREATE_TB)
def recv2str(dict_recv):
	if len(dict_recv) == 0:
		return None
	if  dict_recv.get('disk', 0) != 0:
		temp = ''
		for key in dict_recv['disk']:
			temp += "%s\t\tTotal: %s\tUse%%:: %s\n" %(key.ljust(30), dict_recv['disk'][key]['total'], dict_recv['disk'][key]['percent'])
	mail_str  = " 日  期 :   %s" % time.ctime(dict_recv.get('time_token', time.time()))
	mail_str += "\nHOST_IP：	%s\n" %dict_recv.get('hostip', '0.0.0.0')
	mail_str += "上行带宽：  %s Mbs\n" %dict_recv['band']['send']
	mail_str += "下行带宽：  %s Mbs\n" %dict_recv['band']['receive']
	mail_str += "内存总量：  %s M\n"   %dict_recv['memInfo']['memtotal']
	mail_str += "内存使用率：%s%%\n"   %dict_recv['memInfo']['percent']
	mail_str += "CPU使用率： %s\n"	   %dict_recv['cpu']
	mail_str += "连接数量：  %s\n"     %dict_recv['conn_info'].get('ESTABLISHED', 0)
	if dict_recv['conn_info'].get('SYN_RECV', 0) != 0:
		mail_str += "等待请求：  %s\n"     %dict_recv['conn_info'].get('SYN_RECV', 0)
	if dict_recv['conn_info'].get('TIME_WAIT', 0) != 0:
		mail_str += "超时结束：  %s\n"     %dict_recv['conn_info'].get('TIME_WAIT', 0)
	mail_str += "磁盘使用情况：\n%s\n" %temp
	print mail_str
	return mail_str

def recv2need(dict_recv, result):
	if(len(dict_recv) == 0):
		return None
	config = read_config(CONFIG_PATH)
	flag = False
	if config == None:
	 	return None
	result.clear() 
	if dict_recv.get('band', 0) != 0:
		result['band_send'] = dict_recv['band']['send'];
		result['band_receive'] = dict_recv['band']['receive']
		band = string.atof(config.get('band', 0))
		if flag != True and band != 0 and (float(result['band_send'] >= band or float(result['band_receive']) >= band)):
			print "band is over the nomal level %s(%s)" %(result['band_send'], result['band_receive'])
			flag = True
	if dict_recv.get('disk', 0) != 0:
		result['disk'] = json.dumps(dict_recv['disk'])
		for key in dict_recv['disk']:
			if int((dict_recv['disk'][key]['percent']).replace("%",' ')) > string.atoi(config.get('disk', '0')) and flag != True:
				print "disk is over the nomal level" , dict_recv['disk']
				flag = True
				break
	if dict_recv.get('memInfo', 0) != 0:
		result['mem_total'] = dict_recv['memInfo']['memtotal']
		result['mem_used'] = "%s%%" %dict_recv['memInfo']['percent']
		if flag != True and dict_recv['memInfo']['percent'] > string.atoi(config.get('memory', 0)):
			print "memInfo is over the nomal level %s(%s)" %(result['mem_total'], result['mem_used'])
			flag = True
	if dict_recv.get('cpu', 0) != 0:
		result['cpu'] = dict_recv['cpu']
		if flag != True and float((dict_recv['cpu']).replace('%', ' ')) > string.atoi(config.get('cpu', 0)):
			print "cpu is over the nomal level" , result['cpu']
			flag = True
	if dict_recv.get('hostip', '0.0.0.0') != 0:
		result['ip'] = dict_recv['hostip']
	result['time_token'] = dict_recv.get('time_token', time.time());
	if dict_recv.get('conn_info', 0) != 0:
		result['conn_num'] = dict_recv['conn_info'].get('ESTABLISHED',0)
		if flag != True and result['conn_num'] > string.atoi(config.get('conn_num', 0)):
			print "conn_num is over the nomal level" , result['conn_num']
			flag = True
	return flag

def insert2database(tb_name, dictArg):
	count = len(dictArg)
	if count == 0:
		return None
	sql = "insert into %s( " %tb_name
	parameters = list()
	for key in dictArg:
		sql += key +", "
		parameters.append(dictArg[key])
	sql = sql.strip(' ,')
	sql += r') values(%s' + r',%s' * (count - 1) + ')'
	sqlManager = SqlManager()
	sqlManager.setConnect(DATABASE_NAME, HOST, USER_NAME, PASSWORD, CHAR_SET)
	sqlManager.insertTable(sql, parameters)

def read_config(config_path):
	cf = ConfigParser.ConfigParser()
#	try:
	cf.read(config_path)
	options = cf.options('baseconf')
	'''except Exception, e:
		print e
		return None'''
	config = dict()
	for option in options:
		config[option] = cf.get('baseconf', option)
	return config

def send_mail(title, send_str):
	msg = MIMEText(send_str, 'plain', 'utf-8')
	msg['Subject'] = Header(title, 'utf-8')
	msg['From'] = 'minik_monitor<david_xcy@163.com>'
	msg['To'] = ';'.join(RECEIVER)
	try:
		smtp = smtplib.SMTP()
		smtp.connect(SMTPSERVER)
		smtp.login(SENDER, MAIL_PASSWORD)
		smtp.sendmail(SENDER, RECEIVER, msg.as_string())
	except Exception, e:
		print "send mail to %s error!" % ";".join(RECEIVER)
		print e
	smtp.quit()

def thread_handler():
	global DAILY_TIME
	global MONITOR_DICT
	while True:
		now = time.time()
		if now > DAILY_TIME:
			DAILY_TIME = time.time() + 86400
			for ip in MONITOR_DICT:
				sql_select = "select *from %s where ip = \"%s\" and time_token > %f and time_token < %f order by time_token desc limit 1" %(TB, ip, now - 86400, now)
				sqlManager = SqlManager()
				sqlManager.setConnect(DATABASE_NAME, HOST, USER_NAME, PASSWORD, CHAR_SET)
				result = sqlManager.queryTable(sql=sql_select)
				if result != None and len(result) != 0:
					sysInfo_dict['band'] = {'receive':result[0][3], 'send': result[0][2]}
					sysInfo_dict['cpu'] = result[0][7]
					sysInfo_dict['memInfo'] = {'memtotal': result[0][6], 'percent': result[0][5]}
					sysInfo_dict['disk'] =  json.loads(result[0][4])
					sysInfo_dict['hostip'] = result[0][1]
					sysInfo_dict['time_token'] = result[0][0]
					sysInfo_dict['conn_info'] = {'ESTABLISHED':result[0][8]}
					send_mail(SUBJECT_DAILY, recv2str(sysInfo_dict))

		for ip in MONITOR_DICT:
			if now - MONITOR_DICT[ip] > DISCONN_TIME:
				warning_str = "%s 服务器：%s 超时未发送心跳！\n请登入相应服务器进行查看！" %(time.ctime(time.time()), ip.replace('.', '-'))
#warning_str = "%s %s超时未发送心跳！\n请登入相应服务器进行查看！" %(time.ctime(time.time()), ip)
				send_mail("服务器失联报警邮件，请注意查收", warning_str)
		time.sleep(120)

def main():
	init()
	context = zmq.Context()

	socket = context.socket(zmq.PULL)
	socket.bind("tcp://*:5558")
	watch_thread = threading.Thread(target = thread_handler, name = 'watch_thread')
	watch_thread.setDaemon(True)
	watch_thread.start()
	try:
		while True:
			result = socket.recv_json()
			MONITOR_DICT[result['hostip']] = result['time_token']
			need_dict = dict()
			flag = recv2need(result, need_dict)
			if flag == True:
				send_mail(SUBJECT_WARNING, recv2str(result))
			insert2database(TB, need_dict)
#			print result
	except Exception, e:
		print e
		socket.close()
		context.term()

if __name__ == '__main__':
	main()
